package com.bjc.chapter13;

public class StringTest5 {

    public static void main(String[] args) {
//        test1();
        test2();
    }

    public static void test1() {
        // 常量优化"a"+"b"+"c" 等同于"abc"
        String s1 = "a" + "b" + "c";
        String s2 = "abc";
        /**
         * 最终.java编译成.class，再执行.class
         * String s1 = "abc"
         * String s2 = "abc"
         */
        System.out.println(s1 == s2);
        System.out.println(s1.equals(s2));
    }

    public static void test2() {
        String s1 = "javaEE";
        String s2 = "hadoop";

        String s3 = "javaEEhadoop";
        String s4 = "javaEE" + "hadoop";
        //如果拼接符号前后出现了变量 则相当于在堆空间中 new String() 具体内容为拼接结果 即为new String("javaEEhadoop")
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;

        System.out.println(s3 == s4);// true
        System.out.println(s3 == s5);// false
        System.out.println(s3 == s6);// false
        System.out.println(s3 == s7);// false
        System.out.println(s5 == s6);// false
        System.out.println(s5 == s7);// false
        System.out.println(s6 == s7);// false

        //intern()判断字符串常量池中是否存在javaEEhadoop值 如果存在，则返回常量池中javaEEhadoop的地址
        //如果字符串常量池中不存在javaEEhadoop，则在常量池中加载一份javaEEhadoop，并返回此对象的地址
        String s8 = s6.intern();
        System.out.println(s3 == s8);//true
    }

    public static void test3() {
        String s1 = "a";
        String s2 = "b";
        String s3 = "ab";
        /**
         * 如下的s1+s2的执行细节：
         * StringBuilder s = new StringBuilder();
         * s.append("a");
         * s.append("b");
         * s.toString(); -> 约等于new String("ab");
         * 补充：再jdk5.0之后使用的是StringBuilder,在5.0之前使用的是StringBuffer
         */
        String s4 = s1 + s2;
        System.out.println(s3 == s4);//false
    }

    public static void test4() {
        final String s1 = "a";
        final String s2 = "b";
        String s3 = "ab";
        /**
         * 字符串拼接操作不一定使用的是StringBuilder
         * 如果拼接符号左右两边都是字符串常量或常量引用，则仍然使用编译期优化，即非StringBuilder的方式
         * 针对final修饰类，方法，基本数据类型，引用数据类型的量的结构时，能使用上final的时候建议使用上
         */
        String s4 = s1 + s2;
        System.out.println(s3 == s4); //true
    }

    /**
     * 执行效率：
     * 通过StringBuilder的append()的方式添加字符串的效率要远高于使用String的字符串拼接方式
     *  1.StringBuilder的append()的方式，自始至终只创建过一个StringBuilder的对象
     *  使用String的字符串拼接方式：创建过多个StringBuilder和String的对象
     *  2.使用String的字符串拼接方式：内存中由于创建了较多的StringBuilder和String的对象，内存占用更大
     *  如果进行GC 需要花费额外的时间
     *
     *  改进的空间：在实际开发中，如果基本确定要前前后天添加的字符串长度不高于某个限定值highLevel的情况下，建议使用
     *  StringBuilder s = new StringBuilder(highLevel); //new char[highLevel]
     */
}
